package com.wenjie.original.flex_config.baseInterface;

import cn.hutool.core.bean.BeanUtil;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryOrderBy;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.relation.RelationManager;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.wenjie.original.entity.common.vo.IResVo;
import com.wenjie.original.entity.common.vo.ISelVo;
import com.wenjie.original.entity.common.vo.RestBaseVo;

import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * @author wenjie
 * @Description 对 mybatis-flex的通用ServiceImp进行封装
 * @date 2024/5/22 21:47
 */
public class Cus_ServiceImp<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements CusIService<T> {


    public <S extends T> RestBaseVo<S> list(QueryWrapper queryWrapper, Integer pn, Integer ps, Class<S> tClass) {
        queryWrapper = queryWrapper.from(GenericClass());
        RestBaseVo<S> mRestBaseVo = new RestBaseVo<>();
        List<S> list = this.pageAs(Page.of(pn, ps), queryWrapper, tClass).getRecords();
        long size = this.mapper.selectCountByQuery(queryWrapper);
        mRestBaseVo.setList(list);
        mRestBaseVo.setMax(size);
        return mRestBaseVo;
    }

    @Override
    public <S extends T> RestBaseVo<S> list(QueryWrapper queryWrapper, Class<S> tClass) {
        queryWrapper = queryWrapper.from(GenericClass());
        RestBaseVo<S> mRestBaseVo = new RestBaseVo<>();
        List<S> list = this.listAs(queryWrapper, tClass);
        long size = this.mapper.selectCountByQuery(queryWrapper);
        mRestBaseVo.setList(list);
        mRestBaseVo.setMax(size);
        return mRestBaseVo;
    }


    @Override
    public RestBaseVo list(ISelVo<T> ISelVo) {
        RestBaseVo<Object> restBaseVo = new RestBaseVo<>();
        T bean = BeanUtil.toBean(ISelVo, GenericClass());
        // 获取rest的类型
        Class tClass = genericClass(ISelVo.getClass());
        Page tPage = this.mapper.paginateWithRelationsAs(Page.of(ISelVo.getPn(), ISelVo.getPs()), QueryWrapper.create(bean), tClass);
        restBaseVo.setList(tPage.getRecords());
        restBaseVo.setMax(tPage.getTotalRow());
        return restBaseVo;
    }

    public <S extends IResVo> RestBaseVo<S> list(ISelVo<T> ISelVo, Class<S> tClass) {
        return list(ISelVo, null, null, tClass);
    }

    @Override
    public <S extends IResVo> RestBaseVo<S> list(ISelVo<T> ISelVo, QueryCondition queryCondition, Class<S> tClass) {
        return list(ISelVo, queryCondition, null, tClass);
    }


    @Override
    public <S extends IResVo> RestBaseVo<S> list(ISelVo<T> ISelVo, QueryOrderBy[] queryOrders, Class<S> tClass) {
        return list(ISelVo, null, queryOrders, tClass);
    }


    @Override
    public <S extends IResVo> RestBaseVo<S> list(ISelVo<T> ISelVo, QueryCondition queryCondition, QueryOrderBy[] queryOrderS, Class<S> tClass) {
        RestBaseVo<S> mRestBaseVo = new RestBaseVo<>();
        T bean = BeanUtil.toBean(ISelVo, GenericClass());
        QueryWrapper queryWrapper = QueryWrapper.create(bean);
        if (queryCondition != null) queryWrapper = queryWrapper.where(queryCondition);
        if (queryOrderS != null) {
            queryWrapper = queryWrapper.orderBy(queryOrderS);
        } else {
            // 这个地方不是个好的解决方案  -- 默认 修改时间的倒序排列
            queryWrapper.orderBy("create_time DESC");
        }

        RelationManager.setMaxDepth(10); // 设置递归查询的最大深度
        Page<S> tPage = this.mapper.paginateWithRelationsAs(Page.of(ISelVo.getPn(), ISelVo.getPs()), queryWrapper, tClass);
        mRestBaseVo.setList(tPage.getRecords());
        mRestBaseVo.setMax(tPage.getTotalRow());
        return mRestBaseVo;
    }


    /**
     * @Description 获取枚举的class对象
     * @author wenjie
     * @date 2024/5/23 11:05
     */
    private Class<T> GenericClass() {
        return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
    }


    /**
     * @Description 获取 SelectSelVo对象中的 SelectResVo
     * @author wenjie
     * @date 2024/6/11 14:34
     */
    private <S> Class<S> genericClass(Class selClass) {
        Class declaringClass = selClass.getDeclaringClass();
        Class[] declaredClasses = declaringClass.getDeclaredClasses();
        for (Class declaredClass : declaredClasses) {
            boolean assignableFrom = IResVo.class.isAssignableFrom(declaredClass);
            if (assignableFrom) return declaredClass;
        }
        throw new RuntimeException("未找到SelectSelVo 对应的 SelectResVo");
    }


}
